package com.baseframe.launch;


import com.baseframe.launch.constant.BaseAppConstant;
import com.baseframe.launch.constant.BaseNacosConstant;
import com.baseframe.launch.scan.BeanScanHandler;
import com.baseframe.launch.scan.ImportLauncher;
import com.baseframe.launch.service.BaseLauncherService;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.*;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class BaseApplication {


    public static ConfigurableApplicationContext run(String appName, Class<?>  source, String... args) {


        SpringApplicationBuilder builder = createSpringApplicationBuilder(appName, source, args);
        return builder.run(args);
    }

    public static SpringApplicationBuilder createSpringApplicationBuilder(String appName, Class<?>  source, String... args){
        Assert.hasText(appName, "[appName]服务名不能为空");
        // 读取环境变量，使用spring boot的规则
        ConfigurableEnvironment environment = new StandardEnvironment();
        MutablePropertySources propertySources = environment.getPropertySources();
        propertySources.addFirst(new SimpleCommandLinePropertySource(args));
        propertySources.addLast(new MapPropertySource(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, environment.getSystemProperties()));
        propertySources.addLast(new SystemEnvironmentPropertySource(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, environment.getSystemEnvironment()));
        // 获取配置的环境变量
        String[] activeProfiles = environment.getActiveProfiles();
        // 判断环境:dev、test、prod
        List<String> profiles = Arrays.asList(activeProfiles);

        // 当前使用的环境变量
        List<String> activeProfileList = new ArrayList<>(profiles);
        Function<Object[], String> joinFun = StringUtils::arrayToCommaDelimitedString;
        //创建 SpringApplicationBuilder
        SpringApplicationBuilder builder = new SpringApplicationBuilder(source);

        String profile;

        if (activeProfileList.isEmpty()){
            //默认dev环境
            profile = BaseAppConstant.ACTIVE_DEV;
            activeProfileList.add(profile);
            //设置环境变量
            builder.profiles(profile);
        }else if (activeProfileList.size() == 1){
            profile = activeProfileList.get(0);
        }else {
            // 同时存在dev、test、prod环境时
            throw new RuntimeException("同时存在环境变量:[" + StringUtils.arrayToCommaDelimitedString(activeProfiles) + "]");
        }
        //获取类所在资源路径
//        String startJarPath = source.getClassLoader().getResource("/").getPath().split("!")[0];
        String activePros = joinFun.apply(activeProfileList.toArray());
        System.out.printf("----启动中，读取到的环境变量:[%s]，jar地址:[%s]----%n", activePros, getPath(source));
        Properties props = System.getProperties();
        props.setProperty("spring.application.name", appName);
        props.setProperty("spring.profiles.active", profile);
        props.setProperty("info.version", BaseAppConstant.APPLICATION_VERSION);
        props.setProperty("info.desc", appName);
        props.setProperty("file.encoding", StandardCharsets.UTF_8.name());
        props.setProperty("base.env",profile);
        props.setProperty("base.name",appName);

        Properties defaultProperties = new Properties();
        defaultProperties.setProperty("spring.main.allow-bean-definition-overriding", "true");

        defaultProperties.setProperty("spring.cloud.nacos.config.file-extension", BaseNacosConstant.NACOS_CONFIG_FORMAT);
        defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].data-id", BaseNacosConstant.sharedDataId());
        defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].group", BaseNacosConstant.NACOS_CONFIG_GROUP);
        defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].refresh", BaseNacosConstant.NACOS_CONFIG_REFRESH);
        defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].data-id", BaseNacosConstant.sharedDataId(profile));
        defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].group", BaseNacosConstant.NACOS_CONFIG_GROUP);
        defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].refresh", BaseNacosConstant.NACOS_CONFIG_REFRESH);
        builder.properties(defaultProperties);

        //注册自定义组件
        List<BaseLauncherService> baseLauncherServices = BeanScanHandler.scanBean(BaseLauncherService.class, ImportLauncher.class);
        //排序，依次执行LauncherService 的launcher方法
        baseLauncherServices
                .stream()
                .sorted(Comparator.comparing(BaseLauncherService::getOrder))
                .collect(Collectors.toList())
                .forEach(launcherService -> {
                    System.out.println("launcherService:"+launcherService);
                    launcherService.launcher(builder, appName, profile, isLocalDev());
                });

        builder.environment(environment);

        return builder;
    }

    public static boolean isLocalDev() {
        String osName = System.getProperty("os.name");
        return StringUtils.hasText(osName) && !("LINUX".equalsIgnoreCase(osName));
    }

    public static String getPath(Class<?>  source) {
        String path = source.getProtectionDomain().getCodeSource().getLocation().getPath();
        if (System.getProperty("os.name").contains("dows")) {
            path = path.substring(1);
        }
        if (path.contains("jar")) {
            path = path.substring(0, path.lastIndexOf("."));
            return path.substring(0, path.lastIndexOf("/"));
        }
        return path;
    }

}
